#pragma once

#include "Sock.hpp"
#include <iostream>
#include <string>
#include <functional>
#include <poll.h>
#include <unistd.h>

#define NUM 1024

namespace poll_ns
{
    using func_t = std::function<std::string(std::string)>;
    const uint16_t defaultport = 8080;
    const int defaultsock = -1;
    const int fdnum = 128 * 8;
    class PollServer
    {
    public:
        PollServer(func_t f, uint16_t port = defaultport) : _port(port), _listensock(-1), _f(f)
        {
        }
        ~PollServer()
        {
            if (_listensock != defaultsock)
                close(_listensock);
            if (_fds != nullptr)
                delete[] _fds;
        }

    public:
        void initServer()
        {
            _listensock = Sock::Socket();
            Sock::Bind(_port, _listensock);
            Sock::Listen(_listensock);
            _fds = new struct pollfd[fdnum];
            for (int i = 0; i < fdnum; i++)
            {
                _fds[i].fd = defaultsock;
                _fds[i].events = 0;
                _fds[i].revents = 0;
            }
            _fds[0].fd = _listensock;
            _fds[0].events = POLLIN;
            // _fds[0].revents = 0;
        }
        void start()
        {
            int timeout = 2000;
            for (;;)
            {
                logMessage(DEBUG, "waiting......");
                int n = poll(_fds, fdnum, -1); // 返回值和select相同，都是返回当前的有多少个fd就绪了
                switch (n)
                {
                case 0:
                    logMessage(NORMAL, "time out......");
                    break;
                case -1:
                    logMessage(ERROR, "poll error: %s", strerror(errno));
                    break;
                default:
                    logMessage(NORMAL, "read ready!");
                    handler_event();
                    break;
                }
            }
        }

    public:
        void print()
        {
            for (int i = 0; i < fdnum; i++)
            {
                if (_fds[i].fd == defaultsock)
                    continue;
                std::cout << _fds[i].fd << " ";
            }
            std::cout << std::endl;
        }
        void accepter()
        {
            std::string clientip;
            uint16_t clientport = 0;
            int sock = Sock::Accept(_listensock, &clientip, &clientport);
            if (sock < 0)
            {
                logMessage(ERROR, "socket accept error");
                return;
            }
            logMessage(NORMAL, "socket accept success[%s:%d]", clientip.c_str(), clientport);
            addfd(sock);
        }
        void recver(int pos)
        {
            char buffer[NUM];
            int n = recv(_fds[pos].fd, buffer, sizeof(buffer) - 1, 0);
            if (n > 0)
            {
                logMessage(NORMAL, "get a message: %s", buffer);
            }
            else if (n == 0)
            {
                close(_fds[pos].fd);
                logMessage(NORMAL, "client close!");
                _fds[pos].fd = defaultsock;
                return;
            }
            else
            {
                close(_fds[pos].fd);
                logMessage(ERROR, "%s", strerror(errno));
                _fds[pos].fd = defaultsock;
                return;
            }

            // write
            std::string resp = _f(buffer);
            resp[resp.size()-1] = 0;
#if -DEBUG
            logMessage(DEBUG, "resp size: %d", resp.size());
#endif
            write(_fds[pos].fd, resp.c_str(), resp.size());
        }
        void addfd(const int &sock)
        {
            int i = 0;
            for (; i < fdnum; i++) // 将新的套接字放入辅助数组中
            {
                if (_fds[i].fd == defaultsock)
                    break;
            }
            if (i == fdnum)
            {
                logMessage(WARNING, "server is full");
                close(sock);
            }
            else
            {
                _fds[i].fd = sock;
                _fds[i].events = POLLIN;
            }
        }
        void handler_event()
        {
            for (int i = 0; i < fdnum; i++)
            {
                if (_fds[i].fd == defaultsock)
                    continue;
                if (_fds[i].events & POLLIN)
                {
                    if (_fds[i].fd == _listensock && _fds[i].revents & POLLIN)
                        accepter();
                    else if (_fds[i].revents & POLLIN)
                        recver(i);
                    else{}
                }
            }
            print();
        }

    private:
        int _listensock;
        uint16_t _port;
        func_t _f;
        struct pollfd *_fds;
    };
}
